from PyQt5 import QtCore
from config import DIRECTION_UP, DIRECTION_RIGHT, DIRECTION_NONE, DIRECTION_LEFT, DIRECTION_DOWN
from config import VIEW_HEIGHT, VIEW_WIDTH, UNIT_LENGTH, PATH_PREFIX
import sys
import winsound

#蛇的节点类，只保留了蛇节点的位置和下一次移动方向信息
class SnakeNode:
    row = -1
    column = -1
    direction = DIRECTION_NONE

    def __init__(self, row, column, direction):
        self.row = row
        self.column = column
        self.direction = direction

    def x(self):
        return (self.column - 1)*UNIT_LENGTH

    def y(self):
        return (self.row - 1)*UNIT_LENGTH

    def direct(self):
        return self.direction

    def width(self):
        return UNIT_LENGTH

    def height(self):
        return UNIT_LENGTH

# 蛇类，存储所有蛇的节点，和蛇的属性信息
class RepaintSnake(QtCore.QObject):
    m_node_list = []
    m_death_status = False
    m_reverse_status = False

    def __init__(self, parent=None):
        super().__init__(parent=parent)

        for counter in range(0, 5):
            temp_node = SnakeNode(
                row=VIEW_HEIGHT/2, column=VIEW_WIDTH/2-counter, direction=DIRECTION_RIGHT)
            self.m_node_list.append(temp_node)

    def move(self): #移动方法
        next_direction = self.m_node_list[0].direction

        for node in self.m_node_list:
            temp_direction = next_direction
            next_direction = node.direction
            self.nodeMove(node, temp_direction)

    def getNodeList(self): #返回节点list
        return self.m_node_list

    def setDirection(self, direction): #设置方向
        if abs(self.m_node_list[0].direction) == abs(direction): #同向或者反向则不能改变方向属性
            return

        #由于蛇类只保存属性，而绘制是周期重绘，则会存在这样一个bug：
        #       在重绘周期到来前，连续将蛇方向改变为反向，这样蛇在移动周期到来后，就撞上了第二个节点
        if abs(self.m_node_list[1].direction) == abs(direction):
            return
        #判断是否具备反向状态
        if not self.m_reverse_status: 
            self.m_node_list[0].direction = direction
        else:
            self.m_node_list[0].direction = -1*direction

    def nodeMove(self, node, direction):#私有方法，配合move方法使用

        if node.direction == DIRECTION_UP:
            node.row -= 1
        elif node.direction == DIRECTION_DOWN:
            node.row += 1
        elif node.direction == DIRECTION_LEFT:
            node.column -= 1
        elif node.direction == DIRECTION_RIGHT:
            node.column += 1

        node.direction = direction

    def addTail(self): #添加节点，尾部添加
        self.playAudio(1)
        tail = self.getTail()
        row, column, direction = tail.row, tail.column, tail.direction

        if direction == DIRECTION_UP:
            row += 1
        elif direction == DIRECTION_DOWN:
            row -= 1
        elif direction == DIRECTION_LEFT:
            column += 1
        elif direction == DIRECTION_RIGHT:
            column -= 1

        temp_node = SnakeNode(
            row=row, column=column, direction=direction)

        self.m_node_list.append(temp_node)

    def removeTail(self): #移除节点，尾部移除
        self.playAudio(1)
        if len(self.m_node_list) <= 5:
            return
        node = self.m_node_list.pop(-1)
        del node

    def getReverseStatus(self): #获取反向状态
        return self.m_reverse_status

    def reverseDirection(self):  # 设置为反向状态
        print("吃到了反向豆")
        self.playAudio(2)
        self.m_reverse_status = True

    def resumeDirection(self):  # 反向状态到期，恢复正常状态
        self.m_reverse_status = False

    def getHead(self):
        return self.m_node_list[0]

    def getTail(self):
        return self.m_node_list[-1]

    def getBody(self):
        return self.m_node_list[1:]

    def collision(self, bean):  # 吃到豆后，判断执行对应的操作
        switch = {
            'red': self.addTail,
            'blue': self.removeTail,
            'black': self.reverseDirection
        }
        switch.get(bean.getType())()

    def setDeathStatus(self, status):
        self.m_death_status = status

    def deathStatus(self):
        return self.m_death_status

    def resetSnake(self): #重置蛇的状态
        while len(self.m_node_list) > 0:
            node = self.m_node_list.pop(0)
            del node

        self.m_death_status = False
        self.m_reverse_status = False

        for counter in range(0, 5):    # reset snake
            temp_node = SnakeNode(
                row=VIEW_HEIGHT/2, column=VIEW_WIDTH/2-counter, direction=DIRECTION_RIGHT)
            self.m_node_list.append(temp_node)

    def resumeStatus(self):
        self.m_reverse_status = False

    def getEffectStatus(self):  # 返回是否处于特效状态下，具备任何一种效果都返回对应type
        if self.m_reverse_status:
            return 2

        return -1  # 如果不具备任何一种效果，则返回false

    def playAudio(self, type):
        if type == 1:
            winsound.PlaySound(PATH_PREFIX + "static/audio/score-1.wav",
                               winsound.SND_ASYNC)
        elif type == 2:
            winsound.PlaySound(PATH_PREFIX + "static/audio/score-2.wav",
                               winsound.SND_ASYNC)
